﻿using System;
using System.Collections.Generic;
using GameFramework.Battle.Core;
using Gameplay.PVE.Utils;
using RootMotion.FinalIK;
using UnityEngine;
using Random = UnityEngine.Random;

namespace Gameplay.PVE.Survivor
{
    public class TrackMovement : BulletMovement
    {
        private float moveTime;
        private Vector3 startPosition;
        private BattleUnit target;
        private bool isTrackFinish = false;
        private float startTime;
        private int jumpTimes;
        private List<int> hitTargets = new List<int>();
        private float jumpDistance;
        private bool isMiss;
        private Vector3 targetPosition;
        private Transform targetMissTransform;
        private MapObstacleData missObstacleData;
        
        public override void Start()
        {
            useMovementLifeTime = true;
            hitTargets.Clear();
            nextJumpTime = 0;
            isTrackFinish = false;
            isMiss = false;
            //什么样的子弹可以打歪
            if (bullet.isCritical)
            {
                
            }
            else
            {
                if (bullet.config.miss_rate > 0)
                {
                    isMiss = UnityEngine.Random.Range(0, 1f) < bullet.config.miss_rate;
                }
            }

            if (isMiss)
            {
                InitMiss();
            }
            else
            {
                InitTrack();
            }
            
            jumpTimes = bullet.config.jump_times;
            if (jumpTimes > 0)
            {
                hitTargets.Add(target.unitId);
                var d = bullet.config.GetParam("jumpDistance");
                jumpDistance = d > 0 ? d : 999;
            }

        }

        private void InitMiss()
        {
            startPosition = bullet.Position;
            target = bullet.target.unit;
            var targetTransform = target.AimPoint;
            //两倍距离
            var distance = bullet.config.max_distance;
            distance = Mathf.Max(distance, 5);
            startTime = TimeManager.time;
            //计算角度，往左或者往右偏移0.1~0.3
            var offset = UnityEngine.Random.Range(0.1f, 0.3f);
            var direction = (bullet.Position - targetTransform.position).normalized;
            if (Random.Range(0, 1f) > 0.5f)
            {
                direction = targetTransform.position + Quaternion.AngleAxis(90,Vector3.up) * direction * offset - bullet.Position;
            }
            else
            {
                direction = targetTransform.position + Quaternion.AngleAxis(-90,Vector3.up) * direction * offset - bullet.Position;
            }
            
            moveTime = distance / bullet.speed;
            targetPosition = CollisionManager.Instance.GetRayCastTarget(bullet.Position,direction,distance,ref missObstacleData);
            if (missObstacleData)
            {
                //BattleDebug.LogError(missObstacleData.name);
            }
            else
            {
                targetPosition = bullet.Position + direction.normalized * distance;
            }
        }

        private void InitTrack()
        {
            startTime = TimeManager.time;
            target = bullet.target.unit;
            if (target == null)
            {
                BattleDebug.LogError(bullet.sourceUnit.unitId + " is Null");
            }
            startPosition = bullet.Position;
            if (bullet.speed == 0)
            {
                moveTime = 0;
            }
            else
            {
                moveTime = Vector3.Distance(startPosition, GetTargetPosition()) / bullet.speed;
            }
        }

        private float nextJumpTime;
        
        public override void Update()
        {
            if (nextJumpTime > 0)
            {
                if (TimeManager.time >= nextJumpTime)
                {
                    nextJumpTime = 0;
                    var lastTarget = target;
                    //找到新的目标
                    target = UnitManager.Instance.SearchTarget(bullet.sourceUnit,bullet.sourceSpawner.GetTargetTeam(),bullet.sourceSpawner.searchSort,jumpDistance,hitTargets);
                    if (target == null)
                    {
                        isTrackFinish = true;
                    }
                    else
                    {
                        bullet.target.unit = target;
                        BattleEffectManager.Instance.CreateChainEffect(bullet.config.jump_effect,lastTarget,target);
                        hitTargets.Add(target.unitId);
                        InitTrack();
                    }
                }
                return;
            }
            if (target == null || target.isDead)
            {
                isTrackFinish = true;
                return;
            }
            float t = (TimeManager.time - startTime) / moveTime;
            var targetPosition = GetTargetPosition();
            bullet.Position = Vector3.Lerp(startPosition, targetPosition, t);
            bullet.Forward = targetPosition - startPosition;
            if (t >= 1)
            {
                //isTrackFinish = true;
                if (isMiss)
                {
                    if (missObstacleData)
                    {
                        missObstacleData.OnHit(bullet.config.elements,bullet.sourceUnit,bullet.Position,bullet.Forward,bullet);
                    }
                    HeroEventBubbleManager.Instance.Miss(bullet.sourceUnit.unitId);
                }
                else
                {
                    bullet.OnHit(target);
                }
                //检测有没有弹射
                if (jumpTimes > 0)
                {
                    jumpTimes--;
                    nextJumpTime = TimeManager.time + 0.1f;
                }
                else
                {
                    isTrackFinish = true;
                }
            }
        }

        private Vector3 GetTargetPosition()
        {
            if (isMiss)
            {
                return targetPosition;
            }
            else
            {
                if (bullet.isCritical)
                {
                    return target.GetHitPoint(0).position;
                }
                else
                {
                    return target.AimPoint.position;
                }
            }
        }
        
        public override bool IsEnd()
        {
            return isTrackFinish;
        }
        
    }
}
